package com.diagrammer
{
	import com.diagrammer.event.BaseEvent;
	import com.diagrammer.event.DesignerEvent;
	
	import flash.events.MouseEvent;
	import flash.geom.Point;
	
	import mx.containers.Canvas;
	
	/**
	 * 重新布局所有Render,event.data = Designer
	 * @eventType com.diagrammer.common.event.BaseEvent
	 */	
	[Event(name="relayout", type="com.diagrammer.event.BaseEvent")]
	/**
	 * 容器点击事件，event.data = null
	 * @eventType com.diagrammer.common.event.DesignerEvent
	 */	
	[Event(name="designerClick", type="com.diagrammer.event.DesignerEvent")]
	/**
	 * 容器开始移动事件,event.data = Point(鼠标按下时，在容器中的位置)
	 * @eventType com.diagrammer.common.event.DesignerEvent
	 */	
	[Event(name="designerDragMoveStart", type="com.diagrammer.event.DesignerEvent")]
	/**
	 * 容器正在移动事件,event.data = Point(鼠标的偏移量)
	 * @eventType com.diagrammer.common.event.DesignerEvent
	 */	
	[Event(name="designerDragMoving", type="com.diagrammer.event.DesignerEvent")]
	/**
	 * 容器停止移动事件,event.data = null
	 * @eventType com.diagrammer.common.event.DesignerEvent
	 */	
	[Event(name="designerDragMoveStop", type="com.diagrammer.event.DesignerEvent")]
	/**
	 * 拓扑图中所有Render的容器，继承于<code>mx.containers.Canvas</code>
	 * 
	 * @author Dwei <b>2012-02-27</b>
	 * 
	 */	
	public class Designer extends Canvas
	{
//============================================================================
//parameter
//============================================================================
		/**
		 * 标记容器是否需要重新布局
		 * @private
		 */		
		private var _invalidateLayoutFlag:Boolean;
		
		private var _dragMovableNode:Boolean;
//============================================================================
//constructor
//============================================================================
		public function Designer()
		{
			super();
			//默认为true，需要裁剪超出边缘的内容部分
			clipContent = true;
			//默认为true，第一次生命周期时需要布局Render
			_invalidateLayoutFlag = true;
			//默认为true，可以整体拖动节点
			_dragMovableNode = true;
		}
//============================================================================
//override
//============================================================================
		override protected function childrenCreated():void
		{
			super.childrenCreated();
			initializeHandlers();
		}
		
		override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
		{
			super.updateDisplayList(unscaledWidth, unscaledHeight);
			if (_invalidateLayoutFlag)
			{
				dispatchEvent(new BaseEvent(BaseEvent.RELAYOUT, this));
				_invalidateLayoutFlag = false;
			}
		}
//============================================================================
//public
//============================================================================
		/**
		 * 标记组件，在稍候重新布局Render
		 * 
		 */		
		public function invalidateLayout():void
		{
			_invalidateLayoutFlag = true;
			invalidateDisplayList();
		}
//============================================================================
//protected
//============================================================================
		/**
		 * 初始化Render事伯监听，由createChildren()函数调用。子类需要调用父类该方法 super.initializeHandlers()。
		 * 
		 */		
		protected function initializeHandlers():void
		{
			addEventListener(MouseEvent.MOUSE_DOWN, mouseDown_handler);
		}
//============================================================================
//handler
//============================================================================
		/** 记录鼠标按下时，在容器中的位置 */		
		private var posiBackup:Point;
		/** 标识容器中节点是否在移动 */		
		private var isMoving:Boolean;
		/** 记录鼠标的偏移量 */
		private var offset:Point = new Point();
		protected function mouseDown_handler(event:MouseEvent):void
		{
			event.stopPropagation();
			isMoving = false;
			//保存鼠标到容器原点的距离
			posiBackup = new Point(mouseX, mouseY);
			//添加全局鼠标事件，开始拖拽移动
			stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMove_stage_handler);
			//添加容器上的鼠标释放事件，并解释为在容器上单击事件
			addEventListener(MouseEvent.MOUSE_UP, mouseUp_handler);
		}
		
		protected function mouseUp_handler(event:MouseEvent):void
		{
			event.stopPropagation();
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMove_stage_handler);
			removeEventListener(MouseEvent.MOUSE_UP, mouseUp_handler);
			dispatchEvent(new DesignerEvent(DesignerEvent.DESIGNER_CLICK));
		}
		
		protected function mouseMove_stage_handler(event:MouseEvent):void
		{
			event.stopPropagation();
			//如果容器中节点不能拖拽，移除舞台上的鼠标移动事件监听，并返回
			if (!dragMovableNode)
				stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMove_stage_handler);
			//容器中节点可以拖动，后台添加鼠标释放事件监听（移除此次拖拽的事件监听）
			if (!isMoving)
			{
				//移除容器上的鼠标释放事件监听（不派发节点的单击事件）
				removeEventListener(MouseEvent.MOUSE_UP, mouseUp_handler);
				if (!dragMovableNode) return;
				stage.addEventListener(MouseEvent.MOUSE_UP, mouseUp_stage_handler);
				isMoving = true;
				dispatchEvent(new DesignerEvent(DesignerEvent.DESIGNER_DRAGMOVE_START, posiBackup));
			}
			//开始移动
			offset.x = mouseX - posiBackup.x;
			offset.y = mouseY - posiBackup.y;
			posiBackup.x = mouseX;
			posiBackup.y = mouseY;
			//派发容器 DESIGNER_DRAGMOVING 事件
			dispatchEvent(new DesignerEvent(DesignerEvent.DESIGNER_DRAGMOVING, offset));
		}
		
		protected function mouseUp_stage_handler(event:MouseEvent):void
		{
			event.stopPropagation();
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMove_stage_handler);
			stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUp_stage_handler);
			isMoving = false;
			dispatchEvent(new DesignerEvent(DesignerEvent.DESIGNER_DRAGMOVE_STOP));
		}
//============================================================================
//getter/setter
//============================================================================
		
		/**
		 * 是否可以整体拖动节点
		 */
		public function get dragMovableNode():Boolean
		{
			return _dragMovableNode;
		}
		
		/**
		 * @private
		 */
		public function set dragMovableNode(value:Boolean):void
		{
			_dragMovableNode = value;
		}
	}
}